#! /bin/sh /usr/share/dpatch/dpatch-run
## 70_convertto16bitsaudio.dpatch by  <root@mythserver.home.rodriguez-vudoyra.com>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad mythtv-0.22.0-fixes22952~/libs/libmythtv/avformatdecoder.cpp mythtv-0.22.0-fixes22952/libs/libmythtv/avformatdecoder.cpp
--- mythtv-0.22.0-fixes22952~/libs/libmythtv/avformatdecoder.cpp	2009-11-18 00:23:38.000000000 -0600
+++ mythtv-0.22.0-fixes22952/libs/libmythtv/avformatdecoder.cpp	2009-12-13 00:10:14.000000000 -0600
@@ -459,7 +459,8 @@
       itv(NULL),
       selectedVideoIndex(-1),
       // Audio
-      audioSamples(NULL),
+      audioSamples(NULL),           audioSamples2(NULL),
+      reformat_ctx(NULL),
       allow_ac3_passthru(false),    allow_dts_passthru(false),
       disable_passthru(false),      max_channels(2),
       dummy_frame(NULL),
@@ -474,6 +475,8 @@
     params.prealloced_context = 1;
     audioSamples = (short int *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE *
                                            sizeof(*audioSamples));
+    audioSamples2 = (short int *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE *
+                                           sizeof(*audioSamples2));
     ccd608->SetIgnoreTimecode(true);
 
     bool debug = (bool)(print_verbose_messages & VB_LIBAV);
@@ -509,6 +512,7 @@
     delete m_h264_parser;
 
     av_freep((void *)&audioSamples);
+    av_freep((void *)&audioSamples2);
 
     if (dummy_frame)
     {
@@ -3665,6 +3669,7 @@
                 case CODEC_TYPE_AUDIO:
                 {
                     bool reselectAudioTrack = false;
+                    char *s;
 
                     /// HACK HACK HACK -- begin See #3731
                     if (!GetNVP()->HasAudioIn())
@@ -3691,10 +3696,6 @@
                          (curstream->codec->codec_id == CODEC_ID_DTS));
                     bool using_passthru = do_ac3_passthru || do_dts_passthru;
 
-                    /// XXX HACK: set sample format to signed 16 bit
-                    if (curstream->codec->codec_id == CODEC_ID_TRUEHD)
-                        curstream->codec->sample_fmt = SAMPLE_FMT_S16;
-
                     // detect channels on streams that need
                     // to be decoded before we can know this
                     bool already_decoded = false;
@@ -3768,6 +3769,8 @@
 
                     avcodeclock.lock();
                     data_size = 0;
+                    s = (char *)audioSamples;
+
                     if (audioOut.do_passthru)
                     {
                         data_size = pkt->size;
@@ -3794,6 +3797,44 @@
                                                         &data_size, ptr, len);
                         }
 
+                            // Convert sample format if required (Myth only handles 8 and 16 bits audio)
+                        if (ctx->sample_fmt != SAMPLE_FMT_S16 && ctx->sample_fmt != SAMPLE_FMT_U8)
+                        {
+                            if (reformat_ctx)
+                                av_audio_convert_free(reformat_ctx);
+                            reformat_ctx = av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
+                                                                  ctx->sample_fmt, 1,
+                                                                  NULL, 0);
+                            if (!reformat_ctx)
+                            {
+                                VERBOSE(VB_PLAYBACK, QString("Cannot convert %1 sample format to %2 sample format")
+                                        .arg(avcodec_get_sample_fmt_name(ctx->sample_fmt))
+                                        .arg(avcodec_get_sample_fmt_name(SAMPLE_FMT_S16)));
+
+                                avcodeclock.unlock();
+                                have_err = true;
+                                continue;
+                            }
+
+                            const void *ibuf[6] = {audioSamples};
+                            void *obuf[6] = {audioSamples2};
+                            int istride[6] = {av_get_bits_per_sample_format(ctx->sample_fmt)/8};
+                            int ostride[6] = {2};
+                            int len = data_size/istride[0];
+                            if (av_audio_convert(reformat_ctx, obuf, ostride,
+                                                 ibuf, istride, len) < 0)
+                            {
+                                VERBOSE(VB_PLAYBACK, "av_audio_convert() failed");
+                    
+                                avcodeclock.unlock();
+                                have_err = true;
+                                continue;
+                            }
+
+                            data_size = len * 2;
+                            s = (char *)audioSamples2;
+                        }
+
                         // When decoding some audio streams the number of
                         // channels, etc isn't known until we try decoding it.
                         if ((ctx->sample_rate != audioOut.sample_rate) ||
@@ -3840,11 +3881,10 @@
                     if (audSubIdx != -1)
                     {
                         extract_mono_channel(audSubIdx, &audioOut,
-                                             (char*)audioSamples, data_size);
+                                             s, data_size);
                     }
 
-                    GetNVP()->AddAudioData(
-                        (char *)audioSamples, data_size, temppts);
+                    GetNVP()->AddAudioData(s, data_size, temppts);
 
                     total_decoded_audio += data_size;
 
diff -urNad mythtv-0.22.0-fixes22952~/libs/libmythtv/avformatdecoder.h mythtv-0.22.0-fixes22952/libs/libmythtv/avformatdecoder.h
--- mythtv-0.22.0-fixes22952~/libs/libmythtv/avformatdecoder.h	2009-11-18 00:23:38.000000000 -0600
+++ mythtv-0.22.0-fixes22952/libs/libmythtv/avformatdecoder.h	2009-12-13 00:10:33.000000000 -0600
@@ -15,6 +15,7 @@
 #include "frame.h"
 #include "avcodec.h"
 #include "avformat.h"
+#include "audioconvert.h"
 }
 
 #include "avfringbuffer.h"
@@ -256,6 +257,9 @@
 
     // Audio
     short int        *audioSamples;
+    short int        *audioSamples2;
+    AVAudioConvert   *reformat_ctx;
+
     bool              allow_ac3_passthru;
     bool              allow_dts_passthru;
     bool              disable_passthru;
